<?php
namespace App\Services;

use App\Models\WxUser;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;

class WxUserService
{
    //用户关注的渠道来源
    private $subscribeSceneConf;
    /**
     * 构造函数
     */
    public function __construct()
    {
        $this->subscribeSceneConf = [
            'ADD_SCENE_SEARCH' => '公众号搜索',
            'ADD_SCENE_ACCOUNT_MIGRATION' => '公众号迁移',
            'ADD_SCENE_PROFILE_CARD' => '名片分享',
            'ADD_SCENE_QR_CODE' => '扫描二维码',
            'ADD_SCENEPROFILE LINK' => '图文页内名称点击',
            'ADD_SCENE_PROFILE_ITEM' => '图文页右上角菜单',
            'ADD_SCENE_PAID' => '支付后关注',
            'ADD_SCENE_OTHERS' => '其他',
        ];
    }

    /**
     * 获取用户关注渠道配置
     * @return array
     */
    public function getSubscribeSceneList()
    {
        return $this->subscribeSceneConf;
    }
    /**
     * 传入用户渠道字符串返回渠道名称
     * @param $subscribeScene
     * @return bool|string
     */
    public function getSubscribeSceneName($subscribeScene)
    {
        return $this->subscribeSceneConf[$subscribeScene] ?? '';
    }
    /**
     * 根据接口返回的微信数据更新或插入到微信用户表中
     * @param $apiUserData
     */
    private function upsetUserDataByData($apiUserData)
    {
        if (empty($apiUserData['openid'])){
            throw new \Exception('微信唯一用户标识为空');
        }
        //DB::connection()->enableQueryLog();
        $findUser = WxUser::where('openid', $apiUserData['openid'])->first();
        if (empty($findUser)){
            $findUser = new WxUser;
            //首次关注时间
            $findUser->first_subscribe_time = $apiUserData['subscribe_time'] ?? time();
        }
        $findUser->subscribe = (int) ($apiUserData['subscribe'] ?? 0);
        !empty($apiUserData['openid']) && $findUser->openid = $apiUserData['openid'];
        !empty($apiUserData['unionid']) && $findUser->unionid = $apiUserData['unionid'];
        !empty($apiUserData['nickname']) && $findUser->nickname = preg_replace('/[\x{10000}-\x{10FFFF}]/u', ' ', $apiUserData['nickname']);;
        !empty($apiUserData['sex']) && $findUser->sex = (int) $apiUserData['sex'];
        !empty($apiUserData['language']) && $findUser->language = $apiUserData['language'];
        !empty($apiUserData['country']) && $findUser->country = $apiUserData['country'];
        !empty($apiUserData['province']) && $findUser->province = $apiUserData['province'];
        !empty($apiUserData['city']) && $findUser->city = $apiUserData['city'] ?? '';
        !empty($apiUserData['headimgurl']) && $findUser->headimgurl = $apiUserData['headimgurl'] ?? '';
        !empty($apiUserData['subscribe_time']) && $findUser->subscribe_time = $apiUserData['subscribe_time'];
        !empty($apiUserData['remark']) && $findUser->remark =  $apiUserData['remark'];
        !empty($apiUserData['groupid']) && $findUser->groupid = $apiUserData['groupid'];
        !empty($apiUserData['tagid_list']) && $findUser->tagid_list = $apiUserData['tagid_list'];
        !empty($apiUserData['subscribe_scene']) && $findUser->subscribe_scene = $apiUserData['subscribe_scene'];
        !empty($apiUserData['qr_scene']) && $findUser->qr_scene = $apiUserData['qr_scene'];
        !empty($apiUserData['qr_scene_str']) && $findUser->qr_scene_str = $apiUserData['qr_scene_str'];
        //取消关注时间
        if ($findUser->subscribe == 0){
            $findUser['unsubscribe_time'] = date('Y-m-d H:i:s');
        }
        $findUser->save();
        /*$queries = DB::getQueryLog();
        Log::info('执行语句：', $queries);*/
        return $findUser->toArray();
    }
    /**
     * 获取用户数据(用户一个月未更新数据则自动更新数据)
     * @param $openId
     * @param bool $isRefresh 是否强制刷新数据
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function getUserDataByOpenId($openId, $isRefresh = false)
    {
        $cacheKey = 'wx_user_info_' . $openId;
        $userData = Cache::get($cacheKey);
        if (empty($userData) || $isRefresh){
            $findUser = WxUser::where('openid', $openId)->first();
            //从接口获取数据
            if (empty($findUser) || $isRefresh || $findUser['updated_at'] + 30*86400 < time()){
                $app = EasyWechat::officialAccount();
                $apiRs = $app->user->get($openId);
                //检查微信接口返回结果
                WxErrorService::checkApiResponse($apiRs);
                $userData = $this->upsetUserDataByData($apiRs);
            }
            Cache::put($cacheKey, $userData, 60);
        }
        return $userData;
    }

    /**
     * 同步线上用户数据
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function sync()
    {
        $app = EasyWechat::officialAccount();
        $nextOpenId = null;
        do{
            $apiRs = $app->user->list($nextOpenId);
            //检查微信接口返回结果
            WxErrorService::checkApiResponse($apiRs);
            if (!empty($apiRs['data']['openid'])){
                //按100的大小分割openid，方便从批量获取微信数据的接口获取微信数据并更新
                $collection = collect($apiRs['data']['openid']);
                $openidChunks = $collection->chunk(100);
                $openidChunksList = $openidChunks->toArray();
                foreach ($openidChunksList as $openidList){
                    $userList = $app->user->select(array_values($openidList));
                    //检查微信接口返回结果
                    WxErrorService::checkApiResponse($userList);
                    if (!empty($userList['user_info_list'])){
                        foreach ($userList['user_info_list'] as $apiUserData){
                            $this->upsetUserDataByData($apiUserData);
                        }
                    }
                }
            }
            //总条数大于1w,并且当前获取的条数大于等于1w时,否则马上设空下一个翻页的openid
            if ($apiRs['total'] > $apiRs['count'] && $apiRs['count'] == 10000){
                $nextOpenId = $apiRs['next_openid'];
            }else{
                $nextOpenId = null;
            }
        }while(!empty($nextOpenId));
        return true;
    }
    /**
     * 判断是否首次关注
     * @param $openId
     * @return false|int
     */
    public function isFirstFollow($openId)
    {
        $user = WxUser::where('openid', $openId)->first();
        //为空时
        if (empty($user)){
            return true;
        }
        //未关注过
        if ($user && $user['subscribe'] == 0 && $user['unsubscribe_time'] == 0){
            return true;
        }
        //已关注，但添加时间在2分钟之内
        if ($user && $user['subscribe'] == 1 && time() - $user['add_time'] < 120){
            return true;
        }
        return false;
    }
    /**
     * 设置用户备注
     * @param $openId
     * @param $remark
     * @return bool
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function setRemark($openId, $remark)
    {
        $user = WxUser::where('openid', $openId)->first();
        if (empty($user)){
            throw new \Exception('用户不存在');
        }
        $app = EasyWechat::officialAccount();
        $apiRs = $app->user->remark($openId, $remark);
        //检查微信接口返回结果
        WxErrorService::checkApiResponse($apiRs);
        $user->remark = $remark;
        $user->save();
        return true;
    }

    /**
     * 批量拉黑用户
     * @param $openIds
     * @return bool
     * @throws \Exception
     */
    public function setBlack($openIds)
    {
        $userList = WxUser::whereIn('openid', $openIds)->get();
        if (empty($userList)){
            throw new \Exception('用户不存在');
        }
        $app = EasyWechat::officialAccount();
        $apiRs = $app->user->block($openIds);
        //检查微信接口返回结果
        WxErrorService::checkApiResponse($apiRs);
        WxUser::whereIn('openid', $openIds)->update(['is_lock'=>1]);
        return true;
    }

    /**
     * 批量取消拉黑用户
     * @param $openIds
     * @return bool
     * @throws \Exception
     */
    public function setUnBlack($openIds)
    {
        $userList = WxUser::whereIn('openid', $openIds)->get();
        if (empty($userList)){
            throw new \Exception('用户不存在');
        }
        $app = EasyWechat::officialAccount();
        $apiRs = $app->user->unblock($openIds);
        //检查微信接口返回结果
        WxErrorService::checkApiResponse($apiRs);
        WxUser::whereIn('openid', $openIds)->update(['is_lock'=>0]);
        return true;
    }

    /**
     * 同步黑名单用户
     * @return bool
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function syncBlack()
    {
        WxUser::where('is_lock', 1)->update(['is_lock'=> 0]);
        $app = EasyWechat::officialAccount();
        $nextOpenId = null;
        do{
            $apiRs = $app->user->blacklist($nextOpenId);
            //检查微信接口返回结果
            WxErrorService::checkApiResponse($apiRs);
            if (!empty($apiRs['data']['openid'])){
                WxUser::whereIn('openid', $apiRs['data']['openid'])->update(['is_lock'=>1]);
            }
            //总条数大于1w,并且当前获取的条数大于等于1w时,否则马上设空下一个翻页的openid
            if ($apiRs['total'] > $apiRs['count'] && $apiRs['count'] == 10000){
                $nextOpenId = $apiRs['next_openid'];
            }else{
                $nextOpenId = null;
            }
        }while(!empty($nextOpenId));
        return true;
    }
    /**
     * 添加用户标签
     * @param $openIds
     * @param $tagIds
     * @return bool
     * @throws \Exception
     */
    public function addTag($openIds, $tagIds){
        $userList = WxUser::select('user_id','tagid_list')->whereIn('openid', $openIds)->get();
        if (empty($userList)){
            throw new \Exception('用户不存在');
        }
        $app = EasyWechat::officialAccount();
        //添加标签
        if ($tagIds){
            foreach ($tagIds as $tagId){
                $apiRs = $app->user_tag->tagUsers($openIds, $tagId);
                //检查微信接口返回结果
                WxErrorService::checkApiResponse($apiRs);
            }
        }
        //更新数据库
        foreach ($userList as $user){
            $nowTagidList = $user->tagid_list ?? [];
            $tagIds = array_merge($nowTagidList, $tagIds);
            $tagIds = array_unique($tagIds);
            $user->tagid_list = $tagIds;
            $user->save();
        }
        return true;
    }

    /**
     * 设置用户标签，全部替换
     * @param $openIds
     * @param $tagIds 微信标签ID列表
     * @return bool
     * @throws \Exception
     */
    public function setTag($openIds, $tagIds)
    {
        $userList = WxUser::select('user_id','tagid_list')->whereIn('openid', $openIds)->get();
        if (empty($userList)){
            throw new \Exception('用户不存在');
        }
        $app = EasyWechat::officialAccount();
        //收集现有用户的标签集
        $userTagIds = [];
        foreach ($userList as $user){
            $user['tagid_list'] && $userTagIds = array_merge($userTagIds, $user['tagid_list']);
        }
        $userTagIds = array_unique($userTagIds);
        //先移除旧的标签
        if ($userTagIds){
            foreach ($userTagIds as $userTagId){
                $apiRs = $app->user_tag->untagUsers($openIds, $userTagId);
                //检查微信接口返回结果
                WxErrorService::checkApiResponse($apiRs);
            }
        }
        //再重新添加标签
        if ($tagIds){
            foreach ($tagIds as $tagId){
                $apiRs = $app->user_tag->tagUsers($openIds, $tagId);
                //检查微信接口返回结果
                WxErrorService::checkApiResponse($apiRs);
            }
        }
        //更新数据库
        WxUser::whereIn('openid', $openIds)->update(['tagid_list'=> json_encode($tagIds)]);
        return true;
    }
}